#include "RouletteSelection.h"

void RouletteSelection::select(Solution* &child1, Solution* &child2)
{
	//TODO: Doesn't this need to be multiplied by genePool.size()
    //Trevor: Nope.  Note that when our prepare method populates the
    //wheel, it is assigned ratio of (fitness / totalFitness), which
    //will be a decimal number between 0 and 1.  The sum of ALL 
    //ratios in our solution set is 1, not genePool.size().
    double selection1 = MyRandom::randDbl();
    double selection2 = MyRandom::randDbl();
    
    unsigned int geneSize = genePool.size();
    
    //set the default child to the last solution in the pool.  This should
    //keep us from returning bad pointers when our float-math falls through
    //the cracks.
    child1 = genePool[geneSize - 1];
    child2 = genePool[geneSize - 1];
     
//    cout << "Rolled " << selection1 << " and " << selection2 << endl;

    // Linear search
    for (unsigned int i = 0; i < geneSize; ++i)
    {
        if (selection1 < wheel[i])
        {
//            cout << "Selected: " << i << endl;
            child1 = genePool[i];
            break;
        }
    }

    for (unsigned int i = 0; i < geneSize; ++i)
    {
        if (selection2 < wheel[i])
        {
//            cout << "Selected: " << i << endl;
            child2 = genePool[i];
            break;
        }
    }
    
    //cout << "done performing roulette selection!" << endl;  
}

void RouletteSelection::clean()
{
    wheel.clear();
    genePool.clear();
    totalFitness = 0;
}

void RouletteSelection::prepare(vector<Solution*> newPool)
{
    clean();
    genePool = newPool;
    
    for (unsigned int i = 0; i < genePool.size(); ++i) 
    {
        //TODO: Was this really a good idea?  If we get a bunch of solutions
        //with a fitness of zero, the behavior of this selection is going to
        //be unpredictable...maybe we should do something else instead?
         
        //we need to make sure that totalFitness is never 0, because then we
        //end up dividing by zero.  at the same time, it would be nice to give 
        //fitness-0 solutions a chance to breed, so we can handle both problems 
        //by always adding a tiny amount to the returned fitness.
        totalFitness += genePool[i]->getFitness() + DBL_MIN;
    }
    
    double currentTotal = 0.0;
    
    for (unsigned int i = 0; i < genePool.size(); ++i)  
    {
        currentTotal += (genePool[i]->getFitness() + DBL_MIN) / totalFitness;
        wheel.push_back(currentTotal);
    }
}

Selection* RouletteSelection::getSelection() {
    return new RouletteSelection();
}
